#include <basic_types.h>
#include <mediatypes.h>

#include <api/libc/printf.h>
#include <hld/osd/osddrv.h>
#include <api/libsubt/subt_osd.h>
#include <api/libsubt/lib_subt.h>
#include <hld/hld_dev.h>
#include <hld/sdec/sdec.h>
#include <hld/dis/vpo.h>

UINT32 g_ps_free = 0;
extern struct subt_config_par g_subt_config_par;
extern struct osd_device *osd_dev;
extern BOOL g_subt_show_on;
#define SUBT_PRINTF(...) do{}while(0)
//#define SUBT_PRINTF	libc_printf

static struct subt_osd_region_par g_osd_region_par[MAX_REGION_IN_PAGE];

static UINT8* m_RegionData_nobl[MAX_REGION_IN_PAGE];

static struct OSDRect m_SubtRegion_nobl[MAX_REGION_IN_PAGE];
static BOOL m_UsedRegion_nobl[MAX_REGION_IN_PAGE];
static BOOL m_ShownRegion_nobl[MAX_REGION_IN_PAGE];
static BOOL m_shownRegion_malloc[MAX_REGION_IN_PAGE];

static UINT16 m_TotalHeight = 0;
static UINT16 m_subt_region_w, m_subt_region_h;


static BOOL m_InSubtDecoding = FALSE;

extern unsigned char subt_palette[256][4];
extern BOOL g_update_palette;
static VSCR subt_vscr ;

#define ENTER_SUBT_OSD_API()	{m_InSubtDecoding = TRUE;} //{osal_semaphore_capture(l_subtosd_sema_id,TMO_FEVR);} //dont use semaphore, because this function is called in "draw pixel" funcion which can afect performance --Michael 2007/1/26
#define LEAVE_SUBT_OSD_API()	{m_InSubtDecoding = FALSE;} //{osal_semaphore_release(l_subtosd_sema_id);}
extern UINT32 subt_region_type;
UINT16 RegionOffset_v;

static INT32 Osd_Region_Show_for_sd(UINT8 region_idx, UINT8 on)
{
	INT32 ret = ERR_FAILUE;
	struct OSDRect r1,r2,rect;
    if(m_UsedRegion_nobl[region_idx])
    {
  		MEMCPY(&rect,&(m_SubtRegion_nobl[region_idx]),sizeof(struct OSDRect));
        
        g_subt_config_par.subt_hor_offset = 0;                      
        g_subt_config_par.subt_ver_offset = 0;
        g_subt_config_par.subt_width = m_subt_region_w;
        g_subt_config_par.subt_height = m_subt_region_h;
        
		if(rect.uLeft >= g_subt_config_par.subt_hor_offset)
		{
			r1.uLeft = 0;
			r2.uLeft = rect.uLeft -g_subt_config_par.subt_hor_offset;
			r2.uWidth = r1.uWidth = (rect.uLeft+rect.uWidth> g_subt_config_par.subt_hor_offset+g_subt_config_par.subt_width)? \
				((g_subt_config_par.subt_hor_offset+g_subt_config_par.subt_width>rect.uLeft)?(g_subt_config_par.subt_hor_offset+g_subt_config_par.subt_width-rect.uLeft):0):rect.uWidth;		
		}
		else
		{
			r1.uLeft = g_subt_config_par.subt_hor_offset-rect.uLeft ;
			r2.uLeft = 0;
			r2.uWidth = r1.uWidth = (rect.uLeft+rect.uWidth> g_subt_config_par.subt_hor_offset+g_subt_config_par.subt_width)? \
				(g_subt_config_par.subt_width):((rect.uLeft+rect.uWidth>g_subt_config_par.subt_hor_offset)?(rect.uLeft+rect.uWidth-g_subt_config_par.subt_hor_offset):0);
		}
		if((g_subt_config_par.hd_subtitle_support == 1) && (rect.uWidth<=720))
		{
			if(((720-r2.uWidth)/2) >  g_subt_config_par.subt_hor_offset)
				r2.uLeft +=  g_subt_config_par.subt_hor_offset;
			else
				r2.uLeft += ((720-r2.uWidth)/2);
		}
        if(g_subt_config_par.user_force_pos == TRUE)                // User forcely set position of subtitle show
        {
            UINT16 tmp;
            if((g_subt_config_par.user_force_set_hor_offset != 0xFF) && (g_subt_config_par.user_force_set_hor_offset > g_subt_config_par.subt_ver_offset))
            {
                tmp = g_subt_config_par.user_force_set_hor_offset - g_subt_config_par.subt_hor_offset;
                if(tmp > r2.uLeft)
                {
                    r2.uLeft = tmp;
                }
                if(r2.uLeft + r2.uWidth > m_subt_region_w)
                {
                    r2.uWidth = m_subt_region_w - r2.uLeft;
                }
            } 
		}

		if(rect.uTop >= g_subt_config_par.subt_ver_offset)
		{
			r1.uTop = 0;
			r2.uTop = rect.uTop -g_subt_config_par.subt_ver_offset;
			r2.uHeight = r1.uHeight = (rect.uTop+rect.uHeight> g_subt_config_par.subt_ver_offset+g_subt_config_par.subt_height)? \
				((g_subt_config_par.subt_ver_offset+g_subt_config_par.subt_height>rect.uTop)?(g_subt_config_par.subt_ver_offset+g_subt_config_par.subt_height-rect.uTop):0):rect.uHeight;		
		}
		else
		{
			r1.uTop = g_subt_config_par.subt_ver_offset-rect.uTop ;
			r2.uTop = 0;
			r2.uHeight = r1.uHeight = (rect.uTop+rect.uHeight> g_subt_config_par.subt_ver_offset+g_subt_config_par.subt_height)? \
				(g_subt_config_par.subt_height):((rect.uTop+rect.uHeight>g_subt_config_par.subt_ver_offset)?(rect.uTop+rect.uHeight-g_subt_config_par.subt_ver_offset):0);	
		}
		if((g_subt_config_par.hd_subtitle_support == 1) && (rect.uHeight<=576))
		{
			if(((576-r2.uHeight)/2) >  g_subt_config_par.subt_ver_offset)
				r2.uTop +=  g_subt_config_par.subt_ver_offset;
			else
				r2.uTop += ((576-r2.uHeight)/2);
		}
        UINT16 backup_old_pos;              // used to calculate region offset
        backup_old_pos = r2.uTop;
        if(g_subt_config_par.user_force_pos == TRUE)    
        {
            if(region_idx == 0 )           // Only first region use pos that user set
        {
            UINT16 tmp;
            if((g_subt_config_par.user_force_set_ver_offset != 0xFF) && (g_subt_config_par.user_force_set_ver_offset > g_subt_config_par.subt_ver_offset))
            {
                tmp = g_subt_config_par.user_force_set_ver_offset - g_subt_config_par.subt_ver_offset;
                if(tmp > r2.uHeight)
                {
                    r2.uTop = tmp;
                }
                    if(r2.uTop + r2.uHeight > m_subt_region_h)
                    {
                        r2.uHeight = m_subt_region_h - r2.uTop;
                    }
                    RegionOffset_v = r2.uTop - backup_old_pos;         // calculate offset of first region
                } 
            }
            else                                    // left regions will use region offset
            {
                r2.uTop = r2.uTop + RegionOffset_v;               // The left regions except first region offset
                if(r2.uTop + r2.uHeight > m_subt_region_h)
                {
                    r2.uHeight = m_subt_region_h - r2.uTop;
                }
            } 
        }

		if(on)
        {
            if((g_subt_config_par.hd_subtitle_support == 0) && (rect.uWidth>720))
                return RET_FAILURE;
	
			ret = OSDDrv_RegionWrite2((HANDLE)osd_dev,0,m_RegionData_nobl[region_idx],rect.uWidth,rect.uHeight,&r1,&r2);
        }
        else
        {
         
           	ret = OSDDrv_RegionFill((HANDLE)osd_dev,0,&r2,OSD_TRANSPARENT_COLOR);
        }
	}
	return ret;
}

static INT32 Osd_Region_Show_for_hd(UINT8 region_idx, UINT8 on)
{
	INT32 ret = ERR_FAILUE;
	struct OSDRect r1,r2,rect;
    if(m_UsedRegion_nobl[region_idx])
    {
  		MEMCPY(&rect,&(m_SubtRegion_nobl[region_idx]),sizeof(struct OSDRect));
        
    }
	r1.uLeft=0;
	r1.uTop=0;
	r1.uHeight=rect.uHeight;
	r1.uWidth=rect.uWidth;
	subt_vscr.lpbScr=m_RegionData_nobl[region_idx];
	subt_vscr.vR=r1;
	SUBT_PRINTF("region %d , subt_vscr address=0x%x\n",region_idx,subt_vscr.lpbScr);
	if(on)
        {
            if((g_subt_config_par.hd_subtitle_support == 0) && (rect.uWidth>720))
                return RET_FAILURE;
		
		ret = OSDDrv_RegionWrite((HANDLE)osd_dev, region_idx, &subt_vscr, &r1);
        }
        else
        {
     		ret = OSDDrv_RegionFill((HANDLE)osd_dev,region_idx,&r1,OSD_TRANSPARENT_COLOR);
        }
	
	return ret;
}
static INT32 Osd_Region_Show(UINT8 region_idx, UINT8 on)
{
	if(NULL!= g_osd_region_par[region_idx].g_osd_buf_addr)

		Osd_Region_Show_for_hd(region_idx, on);
	else 
		Osd_Region_Show_for_sd(region_idx, on);
	
}


static INT32 Osd_Region_fill(UINT8 region_idx,UINT8 uColorData)
{
	MEMSET(m_RegionData_nobl[region_idx], uColorData, (m_SubtRegion_nobl[region_idx].uWidth*m_SubtRegion_nobl[region_idx].uHeight));
	if(m_ShownRegion_nobl[region_idx])
		return Osd_Region_Show(region_idx, TRUE);
	
	return RET_SUCCESS;
}


static UINT8 osd_subt_del_region(UINT8 region_idx)
{
    if(!m_UsedRegion_nobl[region_idx])
    {
    	      SUBT_PRINTF("Delete Null region %d\n",region_idx);
		return SUCCESS;
    }
	SUBT_PRINTF("Delete region %d\n",region_idx);
	
	Osd_Region_fill(region_idx, OSD_TRANSPARENT_COLOR);
	
	m_UsedRegion_nobl[region_idx] = FALSE;
	m_ShownRegion_nobl[region_idx] = FALSE;
	g_ps_free -= m_SubtRegion_nobl[region_idx].uWidth*m_SubtRegion_nobl[region_idx].uHeight;
	m_TotalHeight -= m_SubtRegion_nobl[region_idx].uHeight;
	if (g_subt_config_par.hd_subtitle_support && sys_ic_get_chip_id() >= ALI_S3602F)
	{
		if(NULL!= g_osd_region_par[region_idx].g_osd_buf_addr)
		{
		 	OSDDrv_DeleteRegion((HANDLE)osd_dev, region_idx);
			if( g_osd_region_par[region_idx].malloc_flag==TRUE)
			{
				SUBT_PRINTF("free subt osd region buff\n");
				FREE( g_osd_region_par[region_idx].g_osd_buf_addr);
				g_osd_region_par[region_idx].malloc_flag=FALSE;
			}
		 	g_osd_region_par[region_idx].g_osd_buf_addr= NULL;
		 	g_osd_region_par[region_idx].g_osd_buf_len=0;
	
		}
		else
			OSDDrv_DeleteRegion((HANDLE)osd_dev, 0);
	}
	if(m_shownRegion_malloc[region_idx]==TRUE )
	{
		SUBT_PRINTF("free subt osd draw buff\n");
		FREE( m_RegionData_nobl[region_idx]);
		m_RegionData_nobl[region_idx]= NULL;
		m_shownRegion_malloc[region_idx] =FALSE;
	}
	
    return SUCCESS;
}

BOOL osd_region_is_created_no_bl(UINT8 region_idx)
{
    ENTER_SUBT_OSD_API();
    if(g_subt_show_on == FALSE)
    {
        LEAVE_SUBT_OSD_API();
		return FALSE;
    }

    LEAVE_SUBT_OSD_API();
    return m_UsedRegion_nobl[region_idx];
}

static BOOL osd_subt_scale_no_bl(UINT16 screen_width)
{
    enum OSDSys  eOSDSys;
	enum TVSystem tvsys;

    vpo_ioctl((struct vpo_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DIS), VPO_IO_GET_OUT_MODE, (UINT32)(&tvsys));

#ifdef HDTV_SUPPORT
	if(tvsys == NTSC||tvsys == PAL_M||tvsys == PAL_60||tvsys == NTSC_443||tvsys == LINE_720_30||tvsys == LINE_1080_30)
		eOSDSys = OSD_NTSC;
	else
		eOSDSys = OSD_PAL;
#else
	if(tvsys == NTSC||tvsys == PAL_M||tvsys == PAL_60||tvsys == NTSC_443)
		eOSDSys = OSD_NTSC;
	else
		eOSDSys = OSD_PAL;
#endif

    if(g_subt_config_par.osd_get_scale_para != NULL) 
    {
        
	    	UINT32 param = g_subt_config_par.osd_get_scale_para(tvsys, screen_width);
        	OSDDrv_Scale((HANDLE)osd_dev,OSD_SCALE_WITH_PARAM,param);
    }
    else
        	OSDDrv_Scale((HANDLE)osd_dev,OSD_VSCALE_TTX_SUBT,(UINT32)(&eOSDSys));

    return TRUE;
}
static BOOL osd_subt_adjust_region_for_sd(UINT8 region_idx, struct OSDRect *pRegion)
{
    RET_CODE ret;
    UINT32 uSrcWidth, uSrcHeight;
    osd_region_param region_param;

    UINT32 vscr_width = 1920, vscr_height = 1080;

    uSrcWidth = pRegion->uLeft + pRegion->uWidth;
    uSrcHeight = pRegion->uTop + pRegion->uHeight;

    if (uSrcWidth > 1280 || uSrcHeight > 720)
    {
        vscr_width = 1920;
        vscr_height = 1080;
    }
    else if (uSrcWidth > 720 || uSrcHeight > 576)
    {
        vscr_width = 1280;
        vscr_height = 720;
    }
    else
    {
        vscr_width = 720;
        vscr_height = 576;
    }

 
    if (region_idx==0)	
    {
        region_param.region_id =region_idx;

        ret = OSDDrv_IoCtl((HANDLE)osd_dev, OSD_IO_GET_REGION_INFO, (UINT32)&region_param);
        if (ret != RET_SUCCESS)
            return FALSE;

        region_param.region_x = 0;
        region_param.region_y = 0;
        region_param.region_w = m_subt_region_w;
        region_param.region_h = m_subt_region_h;
        region_param.bitmap_x = 0;
        region_param.bitmap_y = 0;
        region_param.bitmap_w = m_subt_region_w;
        region_param.bitmap_h = m_subt_region_h;
        region_param.pixel_pitch = m_subt_region_w;
        region_param.bitmap_addr = 0;
        ret = OSDDrv_DeleteRegion((HANDLE)osd_dev, region_idx);
        if (ret != RET_SUCCESS)
        {
             SUBT_PRINTF("%s : delete region fail\n",__FUNCTION__);
            //SDBBP();
            return FALSE;
        }
        ret = OSDDrv_IoCtl((HANDLE)osd_dev, OSD_IO_CREATE_REGION, (UINT32)&region_param);
        if (ret != RET_SUCCESS)
        {
             SUBT_PRINTF("%s : create region fail\n",__FUNCTION__);
            //SDBBP();
            return FALSE;
        }
      
        osd_subt_scale_no_bl(vscr_width);
        OSDDrv_ShowOnOff((HANDLE)osd_dev, OSDDRV_ON);
        
    }

    return TRUE;
}

static BOOL osd_subt_adjust_region_for_hd(UINT8 region_idx, struct OSDRect *pRegion)
{
	RET_CODE ret;
	UINT32 uSrcWidth, uSrcHeight;
	osd_region_param region_param;
	UINT32 osd_region_len=0;
	UINT8 i=0;
	UINT32 vscr_width = 1920;
	UINT32 vscr_height = 1080;

	uSrcWidth = pRegion->uLeft + pRegion->uWidth;
	uSrcHeight = pRegion->uTop + pRegion->uHeight;
	#ifdef _M3821_
	for(i = 0; i < MAX_REGION_IN_PAGE; i++)
	   {
	
		   if(m_UsedRegion_nobl[i])
		   {
			  // if(m_SubtRegion_nobl[i].uTop+m_SubtRegion_nobl[i].uHeight-1 >= pRegion->uTop)
			  //Colin>>Some special stream may have 1 pixel region overlap, but they must be showed.
			  if(m_SubtRegion_nobl[i].uTop+m_SubtRegion_nobl[i].uHeight+5 >= pRegion->uTop)
			   {
					if(m_SubtRegion_nobl[i].uTop <= pRegion->uTop ||
					   m_SubtRegion_nobl[i].uTop <= pRegion->uTop+pRegion->uHeight-1)
					{
							SUBT_PRINTF("later region is not higher 5 pixel\n");
							pRegion->uTop=m_SubtRegion_nobl[i].uTop+m_SubtRegion_nobl[i].uHeight+5;
					   
					}				  
			   }
		   }
	   }
	#endif
	osd_region_len=((pRegion->uWidth+0xf)&0xfffffff0)*(pRegion->uHeight);
	
	g_osd_region_par[region_idx].g_osd_buf_len=osd_region_len;
	
	SUBT_PRINTF("osd_subt_adjust_region_for_hd:x:%d,y:%d,w:%d,h:%d\n",pRegion->uLeft,pRegion->uTop,pRegion->uWidth,pRegion->uHeight);
	
	if((g_ps_free+osd_region_len)<g_subt_config_par.osd_buf_length)
	{
		g_osd_region_par[region_idx].g_osd_buf_addr=(UINT8 *)(g_ps_free+(g_subt_config_par.osd_buf));

		SUBT_PRINTF("__MM_OSD_BK_ADDR2=0x%x,__MM_OSD2_LEN=0x%x\n",g_subt_config_par.osd_buf,g_subt_config_par.osd_buf_length);
		SUBT_PRINTF("region %d,g_ps_free=0x%x,osd len=0x%x\n",region_idx,(g_ps_free+osd_region_len),g_subt_config_par.osd_buf_length);
	}
	else
	{
	
	      
		g_osd_region_par[region_idx].g_osd_buf_addr= (UINT8 *)MALLOC( g_osd_region_par[region_idx].g_osd_buf_len);
		SUBT_PRINTF("osd2_len is not enough,region %d  size=0x%x\n", region_idx,g_osd_region_par[region_idx].g_osd_buf_len);
		if(NULL== g_osd_region_par[region_idx].g_osd_buf_addr)
		{
			SUBT_PRINTF("region %d Alloc OSD region memory fail\n",region_idx);
			return FALSE;
		}
		g_osd_region_par[region_idx].malloc_flag=TRUE;
		
		
	}
	
    if (uSrcWidth > 1280 || uSrcHeight > 720)
    {
        vscr_width = 1920;
        vscr_height = 1080;
    }
    else if (uSrcWidth > 720 || uSrcHeight > 576)
    {
        vscr_width = 1280;
        vscr_height = 720;
    }
    else
    {
        vscr_width = 720;
        vscr_height = 576;
    }

        MEMSET(&region_param,0,sizeof(osd_region_param));
       

        ret = OSDDrv_IoCtl((HANDLE)osd_dev, OSD_IO_GET_REGION_INFO, (UINT32)&region_param);
        if (ret != RET_SUCCESS)
            return FALSE;
		
	 region_param.region_id = region_idx;
	 region_param.region_x = pRegion->uLeft;
        region_param.region_y = pRegion->uTop;
        region_param.region_w = ((pRegion->uWidth+0xf)&0xfffffff0);
        region_param.region_h = pRegion->uHeight;
        region_param.bitmap_x = 0;
        region_param.bitmap_y = 0;
        region_param.bitmap_w =  ((pRegion->uWidth+0xf)&0xfffffff0);
        region_param.bitmap_h = pRegion->uHeight;
        region_param.pixel_pitch = ((pRegion->uWidth+0xf)&0xfffffff0);
        region_param.bitmap_addr =   g_osd_region_par[region_idx].g_osd_buf_addr;
        ret = OSDDrv_DeleteRegion((HANDLE)osd_dev, region_idx);
		
        if (ret != RET_SUCCESS)
        {
            SUBT_PRINTF("%s : delete region fail\n",__FUNCTION__);
            //SDBBP();
            return FALSE;
        }
		
	SUBT_PRINTF("region_param.regionid=%d\n",region_param.region_id);
	
       ret = OSDDrv_IoCtl((HANDLE)osd_dev, OSD_IO_CREATE_REGION, (UINT32)&region_param);
	   
        if (ret != RET_SUCCESS)
        {
	     SUBT_PRINTF("create region %d fail\n",region_idx);
            //SDBBP();
            return FALSE;
        }
 
	ret=osd_subt_scale_no_bl(vscr_width);
	
	OSDDrv_ShowOnOff((HANDLE)osd_dev, OSDDRV_ON);

    return TRUE;
}

__ATTRIBUTE_RAM_
INT32 osd_subt_create_region_no_bl(UINT8 region_idx, struct OSDRect *pRegion)
{
    UINT8 i;
   
		

    ENTER_SUBT_OSD_API();
    if(g_subt_show_on == FALSE)
    {
        LEAVE_SUBT_OSD_API();
		return FALSE;
    }
  
	SUBT_PRINTF("create region %d, x:%d,y:%d,w:%d,h:%d\n",region_idx,pRegion->uLeft,pRegion->uTop,pRegion->uWidth,pRegion->uHeight);

	 if (g_subt_config_par.hd_subtitle_support && sys_ic_get_chip_id() >= ALI_S3602F)
	{
	if(subt_region_type==OSD_SUBT_RESO_1920X1080||subt_region_type==OSD_SUBT_RESO_1280X720||pRegion->uWidth>m_subt_region_w)
		
		osd_subt_adjust_region_for_hd(region_idx, pRegion);
	
	else
		osd_subt_adjust_region_for_sd(region_idx, pRegion);
	}

    // delete overlap region
    for(i = 0; i < MAX_REGION_IN_PAGE; i++)
    {

        if(m_UsedRegion_nobl[i])
        {
           // if(m_SubtRegion_nobl[i].uTop+m_SubtRegion_nobl[i].uHeight-1 >= pRegion->uTop)
           //Colin>>Some special stream may have 1 pixel region overlap, but they must be showed.
           if(m_SubtRegion_nobl[i].uTop+m_SubtRegion_nobl[i].uHeight-1 > pRegion->uTop)
            {
                 if(m_SubtRegion_nobl[i].uTop <= pRegion->uTop ||
				 	m_SubtRegion_nobl[i].uTop <= pRegion->uTop+pRegion->uHeight-1)
                 {
                    	SUBT_PRINTF("region overlap\n");
				pRegion->uTop=m_SubtRegion_nobl[i].uTop+m_SubtRegion_nobl[i].uHeight;
                   	
                 }                 
            }
        }
    }

    if(m_TotalHeight+pRegion->uHeight >= g_subt_config_par.max_subt_height)
    {
    	 SUBT_PRINTF("Total Height overflow\n");
        for(i = 0; i < MAX_REGION_IN_PAGE; i++)
        {
            if(m_UsedRegion_nobl[i])
                osd_subt_del_region(i);
        }
    }

    if(m_TotalHeight+pRegion->uHeight >= g_subt_config_par.max_subt_height)
    {
        SUBT_PRINTF("too big subt region\n");
        LEAVE_SUBT_OSD_API();
        return ERR_FAILUE;
    }

    if(m_UsedRegion_nobl[region_idx])
    {
    	 SUBT_PRINTF("region %d already exists, delete it\n",region_idx);
        osd_subt_del_region(region_idx);
    }

    //To fix bug reported by E-TEK, subtitle's width is not 16-byte align
    //Michael 2006/3/17
    pRegion->uWidth = ((pRegion->uWidth+0xf)&0xfffffff0); 
    SUBT_PRINTF("create region %d, x:%d,y:%d,w:%d,h:%d\n",region_idx,pRegion->uLeft,pRegion->uTop,pRegion->uWidth,pRegion->uHeight);

	
	if(g_ps_free+pRegion->uWidth*pRegion->uHeight > g_subt_config_par.g_ps_buf_len)
	{
		m_RegionData_nobl[region_idx] = (UINT8 *)MALLOC(pRegion->uWidth*pRegion->uHeight);
		if(m_RegionData_nobl[region_idx] ==NULL)
		{
			SUBT_PRINTF("region %d malloc OSD draw memory fail\n",region_idx);
			return ERR_FAILUE;
		}
		else
			m_shownRegion_malloc[region_idx] =TRUE;
	
	}
	else
	{
		m_RegionData_nobl[region_idx] = g_subt_config_par.g_ps_buf_addr+g_ps_free;
	}
	
	SUBT_PRINTF("region %d show address=0x%x\n",region_idx,m_RegionData_nobl[region_idx]);
	
	g_ps_free += pRegion->uWidth*pRegion->uHeight;

	m_UsedRegion_nobl[region_idx] = TRUE;
      m_ShownRegion_nobl[region_idx] = FALSE;
				
	m_SubtRegion_nobl[region_idx].uLeft = pRegion->uLeft;
	m_SubtRegion_nobl[region_idx].uWidth = pRegion->uWidth;
	m_SubtRegion_nobl[region_idx].uTop = pRegion->uTop;
	m_SubtRegion_nobl[region_idx].uHeight = pRegion->uHeight;	
	m_TotalHeight += m_SubtRegion_nobl[region_idx].uHeight;	
	
  
	Osd_Region_fill(region_idx, OSD_TRANSPARENT_COLOR);

    LEAVE_SUBT_OSD_API();
    return SUCCESS;
}

void osd_subt_enter_no_bl()
{
    enum OSDSys  eOSDSys;
	struct OSDPara	tOpenPara;	
	struct OSDRect tOpenRect,r;
	enum TVSystem tvsys;
	int i;
	

	if(g_subt_show_on == TRUE)
		return;

	if(g_subt_config_par.g_ps_buf_addr==NULL || g_subt_config_par.g_ps_buf_len == 0)
		return;

	SUBT_PRINTF("lib subtitle enter.\n");
	
    //soc_printf("osd_subt_enter_no_bl\n");
    vpo_ioctl((struct vpo_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DIS), VPO_IO_GET_OUT_MODE, (UINT32)(&tvsys));

#ifdef HDTV_SUPPORT
	if(tvsys == NTSC||tvsys == PAL_M||tvsys == PAL_60||tvsys == NTSC_443||tvsys == LINE_720_30||tvsys == LINE_1080_30)
		eOSDSys = OSD_NTSC;
	else
		eOSDSys = OSD_PAL;
#else
	if(tvsys == NTSC||tvsys == PAL_M||tvsys == PAL_60||tvsys == NTSC_443)
		eOSDSys = OSD_NTSC;
	else
		eOSDSys = OSD_PAL;
#endif

#if (COLOR_N==4)
	tOpenPara.eMode = OSD_4_COLOR;
#elif (COLOR_N==16)
	tOpenPara.eMode = OSD_16_COLOR;
#elif (COLOR_N==256)
	tOpenPara.eMode = OSD_256_COLOR;
#endif
	tOpenPara.uGAlphaEnable = 0;
	tOpenPara.uGAlpha = 0x0f;

    m_subt_region_w = 720;
    m_subt_region_h = 576;

    if(g_subt_config_par.hd_subtitle_support)
    {
    	tOpenRect.uLeft = 0;//SUBT_HOR_OFFSET;
    	tOpenRect.uWidth = m_subt_region_w; // SUBT_WIDTH;
    	tOpenRect.uTop = 0;//SUBT_VER_OFFSET;
    	tOpenRect.uHeight = m_subt_region_h; // SUBT_HEIGHT;
   
    	r.uLeft = 0;
    	r.uTop = 0;
    	r.uWidth =tOpenRect.uWidth;
    	r.uHeight =tOpenRect.uHeight;	
    }
    else
    {
    	tOpenRect.uLeft = g_subt_config_par.subt_hor_offset;
    	tOpenRect.uWidth = g_subt_config_par.subt_width;
    	tOpenRect.uTop = g_subt_config_par.subt_ver_offset;
    	tOpenRect.uHeight = g_subt_config_par.subt_height;
    	
    	r.uLeft = 0;
    	r.uTop = 0;
    	r.uWidth =g_subt_config_par.subt_width;
    	r.uHeight =g_subt_config_par.subt_height;	
    }
       
	osd_dev = (struct osd_device *)dev_get_by_id(HLD_DEV_TYPE_OSD, g_subt_config_par.osd_layer_id);
	
	OSDDrv_Close((HANDLE)osd_dev);
	OSDDrv_Open((HANDLE)osd_dev, &tOpenPara);
	osal_task_sleep(20);
	
	
	OSDDrv_CreateRegion((HANDLE)osd_dev, 0, &(tOpenRect), NULL);
	OSDDrv_ModifyPallette((HANDLE)osd_dev, OSD_TRANSPARENT_COLOR, 0x10, 0x80, 0x80, 0); 
	OSDDrv_RegionFill((HANDLE)osd_dev,0,&r, OSD_TRANSPARENT_COLOR);
	osd_subt_scale_no_bl(m_subt_region_w);


	OSDDrv_ShowOnOff((HANDLE)osd_dev, OSDDRV_ON);
	g_update_palette = FALSE;

	
	subt_region_type = 0xFFFFFFFF;

	g_subt_show_on = TRUE;
	
      MEMSET(subt_palette,0,256*4);
	m_TotalHeight = 0;
	
	MEMSET(g_subt_config_par.g_ps_buf_addr,OSD_TRANSPARENT_COLOR,g_subt_config_par.g_ps_buf_len);
    for(i = 0; i < MAX_REGION_IN_PAGE; i++)
    {
		m_RegionData_nobl[i] = g_subt_config_par.g_ps_buf_addr;
		m_UsedRegion_nobl[i] = FALSE;
		m_ShownRegion_nobl[i] = FALSE;
		m_shownRegion_malloc[i]=FALSE;
		MEMSET(&(m_SubtRegion_nobl[i]),0,sizeof(struct OSDRect));
    }

    for(i=0;i<MAX_REGION_IN_PAGE;i++)
	{
		g_osd_region_par[i].g_osd_buf_addr = 0;
		g_osd_region_par[i].g_osd_buf_len = 0;
		g_osd_region_par[i].malloc_flag = FALSE;
		
	}
	g_ps_free = 0;
   
}


void osd_subt_leave_no_bl()
{
    int i;
    UINT8 region_idx=0;

    while(m_InSubtDecoding == TRUE)
    {
        OS_TaskSleep(1);
    }
    
    if(g_subt_show_on == FALSE)
		return;

	g_subt_show_on = FALSE;

	SUBT_PRINTF("lib subtitle leave.\n");
        
       osd_dev = (struct osd_device *)dev_get_by_id(HLD_DEV_TYPE_OSD,g_subt_config_par.osd_layer_id);
	OSDDrv_ShowOnOff((HANDLE)osd_dev, OSDDRV_OFF);
	
	for(region_idx=0;region_idx<MAX_REGION_IN_PAGE;region_idx++)
	{
		if (g_subt_config_par.hd_subtitle_support && sys_ic_get_chip_id() >= ALI_S3602F)
		{
	
			if(NULL!= g_osd_region_par[region_idx].g_osd_buf_addr)
			{
		 		OSDDrv_DeleteRegion((HANDLE)osd_dev, region_idx);
				if( g_osd_region_par[region_idx].malloc_flag==TRUE)
				{
					SUBT_PRINTF("free region:%d  0x%x\n",region_idx,g_osd_region_par[region_idx].g_osd_buf_addr);
					FREE( g_osd_region_par[region_idx].g_osd_buf_addr);
					g_osd_region_par[region_idx].malloc_flag=FALSE;
				}
		 			g_osd_region_par[region_idx].g_osd_buf_addr= NULL;
		 			g_osd_region_par[region_idx].g_osd_buf_len=0;	
			}
		}
		else
			OSDDrv_DeleteRegion((HANDLE)osd_dev, 0);		
	
		if(m_shownRegion_malloc[region_idx]==TRUE )
		{
			SUBT_PRINTF("free draw:%d 0x%x\n",region_idx,m_RegionData_nobl[region_idx]);
			FREE( m_RegionData_nobl[region_idx]);
			m_RegionData_nobl[region_idx]= NULL;
			m_shownRegion_malloc[region_idx] =FALSE;
		}
	}
	OSDDrv_Close((HANDLE)osd_dev);
	

}

void osd_subt_set_clut_no_bl(UINT8 entry_id,UINT8 y,UINT8 cb,UINT8 cr,UINT8 t)
{
    ENTER_SUBT_OSD_API();
    if(g_subt_show_on == TRUE)
    {
		subt_palette[entry_id][0]=y; 
		subt_palette[entry_id][1]=cb; 
		subt_palette[entry_id][2]=cr;
		subt_palette[entry_id][3]=t; 
		g_update_palette = TRUE;
		

    }
    LEAVE_SUBT_OSD_API();
}

void osd_subt_update_clut_no_bl()
{
    if(g_update_palette)
    {
        OSDDrv_SetPallette((HANDLE)osd_dev, (UINT8 *)subt_palette, 256,OSDDRV_YCBCR);
        g_update_palette = FALSE;
    }
        
}

__ATTRIBUTE_RAM_
INT32 osd_subt_delete_region_no_bl(UINT8 region_idx)
{
    INT32 ret = ERR_FAILUE;
    ENTER_SUBT_OSD_API();
	if(g_subt_show_on == FALSE)
	{
		ret = ERR_FAILUE;
	}
    	else
    	{
	
        	ret = osd_subt_del_region(region_idx);
       }
    LEAVE_SUBT_OSD_API();
    return ret;
}

__ATTRIBUTE_RAM_
void osd_subt_clear_page_no_bl()
{
	UINT8 i;

    ENTER_SUBT_OSD_API();
    
	if(g_subt_show_on == FALSE)
	{
        LEAVE_SUBT_OSD_API();
		return;
	}
	SUBT_PRINTF("%s\n", __FUNCTION__);
	for(i=0;i<MAX_REGION_IN_PAGE;i++)
	{
        if(m_UsedRegion_nobl[i] && m_ShownRegion_nobl[i])
        {
            SUBT_PRINTF("%s: show off region(%d).\n", __FUNCTION__, i);
        
            osd_subt_del_region(i);
        }
        else
        {
            SUBT_PRINTF("%s: show off NULL region(%d).\n", __FUNCTION__, i);
        }
	}
    LEAVE_SUBT_OSD_API();
}

__ATTRIBUTE_RAM_
INT32 osd_subt_region_show_no_bl(UINT8 region_idx,UINT8 on)
{
    INT32 ret = ERR_FAILUE;

    ENTER_SUBT_OSD_API();
	if(g_subt_show_on == FALSE)
		ret = ERR_FAILUE;
    else
    {
	    SUBT_PRINTF("%s, region_idx = %d, on = %d\n", __FUNCTION__, region_idx, on);
		
        if(m_UsedRegion_nobl[region_idx])
        {
            if(on && m_ShownRegion_nobl[region_idx] == FALSE)
            {
			 m_ShownRegion_nobl[region_idx] = TRUE;
			 ret = Osd_Region_Show(region_idx,on);
	          
            }
            else if((!on) && m_ShownRegion_nobl[region_idx] == TRUE)
            {
			m_ShownRegion_nobl[region_idx] = FALSE;
			 ret = Osd_Region_Show(region_idx,on);
	            
            }
            else if(on && m_ShownRegion_nobl[region_idx])
            {
      			 m_ShownRegion_nobl[region_idx] = TRUE;
			ret = Osd_Region_Show(region_idx,on);
	          
            }
        }
        else
        {
            SUBT_PRINTF("%s: show NULL region(%d).\n", __FUNCTION__, region_idx);
            ret = ERR_FAILUE;
        }
    }
    LEAVE_SUBT_OSD_API();
    return ret;
}

__ATTRIBUTE_RAM_
INT32 osd_subt_draw_pixel_no_bl(UINT8 region_idx,UINT16 x,UINT16 y,UINT8 data)
{
    INT32 ret;

    ENTER_SUBT_OSD_API();
	
		

    if(g_subt_show_on == FALSE)
    {
		ret = ERR_FAILUE;
    }
    else
    {
		
	    if(m_UsedRegion_nobl[region_idx])
	    {
            if(x >= m_SubtRegion_nobl[region_idx].uWidth || y >= m_SubtRegion_nobl[region_idx].uHeight)
            {
                SUBT_PRINTF("%s: out of region(%d), x = %d, y = %d, width = %d, height = %d.\n", \
                    __FUNCTION__, region_idx, x, y, m_SubtRegion_nobl[region_idx].uWidth, m_SubtRegion_nobl[region_idx].uHeight);
               //ASSERT(0);
                ret = ERR_FAILUE;
            }
	
		
	     else
            {
			*(m_RegionData_nobl[region_idx]+x+y*m_SubtRegion_nobl[region_idx].uWidth) = data;
			ret = SUCCESS;
            }
    
	    }
        else
        {
            SUBT_PRINTF("%s: draw NULL region(%d).\n", __FUNCTION__, region_idx);
            ret =  ERR_FAILUE;
        }
    }
    LEAVE_SUBT_OSD_API();
    return ret;
}


INT32 osd_subt_get_region_addr_no_bl(UINT8 region_idx,UINT16 y, UINT32 *addr)
{
    INT32 ret = SUCCESS;
	
    ENTER_SUBT_OSD_API();
	
    if(g_subt_show_on == FALSE)
        ret = ERR_FAILUE;

	if(!m_UsedRegion_nobl[region_idx])
		ret = ERR_FAILUE;

	if(y >= m_SubtRegion_nobl[region_idx].uHeight)
		ret = ERR_FAILUE;

	*addr = (UINT32)(m_RegionData_nobl[region_idx]+y*(m_SubtRegion_nobl[region_idx].uWidth));
	
    LEAVE_SUBT_OSD_API();
    return ret;
}

INT32 osd_subt_display_define_no_bl(struct sdec_display_config *cfg)
{
	UINT32 region_type = 0xFFFFFFFF;
	
	if(g_subt_show_on != TRUE)
		return 0;
	
	if(cfg->display_height <= 480)
	{
		region_type = OSD_SUBT_RESO_720X480;
	}
	else if(cfg->display_height <= 576)
	{
		region_type = OSD_SUBT_RESO_720X576;
	}
	else if(cfg->display_height <= 720)
	{
		region_type = OSD_SUBT_RESO_1280X720;
	}
	else if(cfg->display_height <= 1080)
	{
		region_type = OSD_SUBT_RESO_1920X1080;
	}
	else
	{
		;
	}
	if(region_type != 0xFFFFFFFF && region_type != subt_region_type)
	{
		subt_region_type = region_type;
		osd_dev = (struct osd_device *)dev_get_by_id(HLD_DEV_TYPE_OSD,g_subt_config_par.osd_layer_id);
		OSDDrv_IoCtl(osd_dev, OSD_IO_SUBT_RESOLUTION, subt_region_type);
		SUBT_PRINTF("\nset osd type %d .     ",subt_region_type);
	}
	return 0;
}

